package dao

import (
	"context"
	"errors"
	"go.uber.org/zap"
	"gorm.io/gorm"
	"seichat/biz"
	"seichat/models"
)

type CommunityDao interface {
	CheckCommunityExist(ctx context.Context, name string) (*models.Community, bool)
	CreateCommunity(ctx context.Context, community *models.Community) error
	GetCommunityListByRelations(ctx context.Context, relation []*models.Relation) (*[]models.Community, error)
	FindCommunityByName(ctx context.Context, cname string) (*models.Community, bool)
	JoinCommunity(ctx context.Context, communityID uint, ownerId uint, relationType int) error
}
type GormCommunityDao struct {
	DB *gorm.DB
}

func NewCommunityDao(db *gorm.DB) CommunityDao {
	return &GormCommunityDao{
		DB: db,
	}
}
func (c *GormCommunityDao) CheckCommunityExist(ctx context.Context, name string) (*models.Community, bool) {
	com := models.Community{}
	tx := c.DB.WithContext(ctx).Where("name = ?", name).First(&com)
	err := handleGormError(tx)
	if err != nil {
		zap.S().Error("数据库异常", zap.Error(err))
		return nil, false
	}
	if tx.RowsAffected == 1 {
		return &com, true
	}
	return nil, false
}

// CreateCommunity 新建群
func (c *GormCommunityDao) CreateCommunity(ctx context.Context, community *models.Community) error {
	// 1. 开启事务
	tx := c.DB.WithContext(ctx).Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()
	// 2. 创建群
	if err := tx.Create(&community).Error; err != nil {
		zap.S().Error("创建群失败", zap.Error(err))
		tx.Rollback()
		if errors.Is(err, gorm.ErrDuplicatedKey) {
			return biz.AlreadyCommunity
		}
		return biz.DBError
	}
	// 3. 构建关系对象并插入
	relation := &models.Relation{
		OwnerId:  community.OwnerId,
		TargetID: community.ID,
		Type:     2, // 群类型
	}
	if err := tx.Create(relation).Error; err != nil {
		zap.S().Error("创建关系失败", zap.Error(err))
		tx.Rollback()
		if errors.Is(err, gorm.ErrDuplicatedKey) {
			return biz.RelationAlreadyExists
		}
		return biz.DBError
	}
	// 4. 提交事务
	if err := tx.Commit().Error; err != nil {
		zap.S().Error("提交事务失败", zap.Error(err))
		return biz.DBError
	}
	return nil
}

// GetCommunityListByRelations 根据关系表 返回群列表
func (c *GormCommunityDao) GetCommunityListByRelations(ctx context.Context, relation []*models.Relation) (*[]models.Community, error) {
	communityID := make([]uint, 0)
	for _, v := range relation {
		cid := v.TargetID
		communityID = append(communityID, cid)
	}
	community := make([]models.Community, 0)
	tx := c.DB.WithContext(ctx).Where("id in ?", communityID).Find(&community)
	if err := handleGormError(tx); err != nil {
		return nil, err
	}
	if tx.RowsAffected == 0 {
		return nil, biz.RecordNotFound
	}
	return &community, nil
}

// FindCommunityByName 根据群昵称查找群
func (c *GormCommunityDao) FindCommunityByName(ctx context.Context, cname string) (*models.Community, bool) {
	community := models.Community{}
	tx := c.DB.WithContext(ctx).Where("name = ?", cname).First(&community)
	if err := handleGormError(tx); err != nil {
		zap.S().Error("查找群失败:", zap.Error(err))
		return nil, false
	}
	if tx.RowsAffected == 0 {
		zap.S().Error(biz.RecordNotFound)
		return nil, false
	}
	return &community, true
}

// JoinCommunity 根据群昵称搜索并加入群
func (c *GormCommunityDao) JoinCommunity(ctx context.Context, communityID uint, ownerId uint, relationType int) error {
	tx := c.DB.WithContext(ctx).Create(&models.Relation{
		OwnerId:  ownerId,
		TargetID: communityID,
		Type:     relationType,
	})
	if err := handleGormError(tx); err != nil {
		return err
	}
	if tx.RowsAffected == 0 {
		return biz.RelationCreateFailed
	}
	return nil
}
